import * as t from 'three';
import type { Scene, Mesh, PerspectiveCamera, WebGLRenderer } from 'three';
import GUI from "three/examples/jsm/libs/lil-gui.module.min";

import modelEventManager from './modelEventManager';
class SceneManager {
    scene:Scene |null= null;
    mesh: Mesh | null = null;
    camera: PerspectiveCamera | null = null;
    renderer: WebGLRenderer | null = null;
    gui: GUI | null = null;
    createGUI(mesh:Mesh, pointLight:t.PointLight) {
        const gui = new GUI();
        // gui界面上增加交互界面，改变obj对应属性
        gui.add(mesh.position, 'x', 0, 1000);
        gui.add(mesh.position, 'y', 0, 1000);
        gui.add(mesh.position, 'z', 0, 1000);
        gui.add(pointLight.position, 'x', 0, 1000);
        gui.add(pointLight.position, 'y', 0, 1000);
        gui.add(pointLight.position, 'z', 0, 1000);
        gui.add(pointLight, 'intensity', 0, 100.0);
    }
    clear() {
        // this.scene.dispose();
        // this.mesh!.dispose();
        // this.camera!.dispose();
        this.renderer!.dispose();
        this.gui?.destroy();
    }
    // 创建一个新的几何体
    createBufferGeometry() {
        const vectices = new Float32Array([
            // 编写顶点的坐标数据
            0, 0, 0,
            80, 0, 0,
            80, 80, 0,
            0, 80, 0
        ]);

        const index = new Uint32Array([ 0, 1, 2, 0, 2, 3 ]);
        const bufferGeometry = new t.BufferGeometry();
        const attribute = new t.BufferAttribute(vectices, 3);
        // 设置几何体的顶点位置属性
        bufferGeometry.attributes.position = attribute;
        bufferGeometry.index = new t.BufferAttribute(index, 1);

        const normals = new Float32Array([
            0, 0, 1,
            0, 0, 1,
            0, 0, 1,
            0, 0, 1,
        ]);

        bufferGeometry.attributes.normal = new t.BufferAttribute(normals, 3);
        const meterial = new t.PointsMaterial({
            color: 'purple',
            size: 10,
            side:t.DoubleSide
        });
        const points = new t.Points(bufferGeometry, meterial);
        this.scene?.add(points);
        // this.createLine(bufferGeometry);
        return this.createGenmetry(bufferGeometry, meterial);

    }
    createBoxGeometry() {
        const boxGeometry = new t.BoxGeometry(100, 100, 100);
        const meterial = new t.MeshLambertMaterial({
            color: 'green',
            side:t.DoubleSide
        });
        return this.createGenmetry(boxGeometry, meterial);
    }
    createGenmetry<T extends t.BufferGeometry<t.NormalBufferAttributes>, K extends t.Material>(genmetry:T, material:K) {
        // 默认正面刻间,背面不可见
        const mesh = new t.Mesh(genmetry, material);
        // 设置在场景中的位置
        mesh.position.set(0, 0, 0);
        mesh.castShadow = true; // 物体接收阴影
        mesh.receiveShadow = true; // 物体接收阴影
        this.scene?.add(mesh);
        return mesh;
    }

    // 线模型
    createLine(geometry:t.BufferGeometry) {
        const meterial = new t.LineBasicMaterial({
            color:'yellow'
        });
        // const line = new t.Line(geometry, meterial);
        const line2 = new t.LineLoop(geometry, meterial);
        // const line = new t.LineLoop(geometry, meterial);
        // this.scene?.add(line);
        this.scene?.add(line2);
    }
    createPointLight() {
        // 添加点光源
        const pointLight = new t.PointLight('skyblue', 1.0);
        pointLight.position.set(200, 100, 50);
        pointLight.decay = 0.0;
        this.scene!.add(pointLight);

        // 可视化点光源

        // const pointLightHelper = new t.PointLightHelper(pointLight, 100);

        // this.scene!.add(pointLightHelper);
    }
    init() {
        if (!this.scene) {
            const sceneBox = document.querySelector('#scene') as HTMLElement;
            this.scene = new t.Scene();
            // const mesh = this.createBufferGeometry();
            const mesh = this.createBoxGeometry();
            // 三位辅助坐标轴
            const axesHelper = new t.AxesHelper(150);
            this.scene.add(axesHelper);
            // 定义相机输出画布的尺寸
            const { width, height } = sceneBox!.getBoundingClientRect();
            // 设置相机的四个参数

            // 生成一个透视投影相机相机
            this.camera = new t.PerspectiveCamera(30, width/height, 0.1, 3000);
            // 设置相机的位置
            this.camera.position.set(400, 200, 300);
            // 相机的视线  观察目标点的坐标
            this.camera.lookAt(0, 0, 100); // 指向网格模型

            // 渲染器
            this.renderer = new t.WebGLRenderer({
                antialias:true, // 锯齿属性
            });
           this.renderer!.setSize(width, height);
           // 必写的 像素比
           this.renderer!.setPixelRatio(window.devicePixelRatio);
           // 执行渲染操作,类比相机的拍照动.作
           this.renderer.render(this.scene, this.camera);
           sceneBox?.appendChild(this.renderer.domElement);
           modelEventManager.initEvent();
           modelEventManager.addAnimate(mesh);
           this.createPointLight();
            //  this.createGUI(mesh, pointLight);
        }

    }
}

export default new SceneManager();
